using System.Linq.Expressions;
using System.Reflection;
using SqlSugar;
using zhwy.saas.api.Services.Sinterface;

namespace zhwy.saas.api.Repository
{
    public class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEntity : class, new()
    {
        private readonly ISqlSugarClient _dbContext;
        private readonly ICurrentUserService _currentUserService;

        public BaseRepository(ISqlSugarClient dbContext,
            ICurrentUserService currentUserService)
        {
            _dbContext = dbContext;
            _currentUserService = currentUserService;
        }

        public ISqlSugarClient DbContext => _dbContext;

        private bool HasTenantId()
        {
            // 使用反射检查 TEntity 类型是否包含 TenantId 属性
            PropertyInfo tenantIdProperty = typeof(TEntity).GetProperty("Tenant_id");
            return tenantIdProperty != null ? true : false;
        }

        #region 查询
        public async Task<TEntity> GetByIdAsync(object id)
        {
            if (HasTenantId())
            {
                return await _dbContext.Queryable<TEntity>()
                    .Where($"tenant_id = {_currentUserService.GetTenantId()}")
                    .InSingleAsync(id);
            }
            else
            {
                return await _dbContext.Queryable<TEntity>().InSingleAsync(id);
            }
        }

        public async Task<List<TEntity>> GetAllAsync()
        {
            if (HasTenantId())
            {
                return await _dbContext.Queryable<TEntity>()
                    .Where($"tenant_id = {_currentUserService.GetTenantId()}")
                    .ToListAsync();
            }
            else
            {
                return await _dbContext.Queryable<TEntity>().ToListAsync();
            }
        }

        public async Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate)
        {
            if (HasTenantId())
            {
                return await _dbContext.Queryable<TEntity>()
                    .Where($"tenant_id = {_currentUserService.GetTenantId()}")
                    .Where(predicate)
                    .ToListAsync();
            }
            else
            {
                return await _dbContext.Queryable<TEntity>().Where(predicate).ToListAsync();
            }
        }

        public async Task<(List<TEntity> Items, int Total)> GetPagedListAsync(Expression<Func<TEntity, bool>> predicate, int pageIndex, int pageSize)
        {
            RefAsync<int> total = 0;
            var items = new List<TEntity>();
            if (HasTenantId())
            {
                items = await _dbContext.Queryable<TEntity>()
                  .Where($"tenant_id = {_currentUserService.GetTenantId()}")
                  .Where(predicate)
                  .ToPageListAsync(pageIndex, pageSize, total);
            }
            else
            {
                items = await _dbContext.Queryable<TEntity>()
                   .Where(predicate)
                   .ToPageListAsync(pageIndex, pageSize, total);
            }
            return (items, total);
        }
        #endregion

        #region 增删改
        public async Task<bool> AddAsync(TEntity entity)
        {
            return await _dbContext.Insertable(entity).ExecuteCommandAsync() > 0;
        }

        /// <summary>
        /// 新增实体并返回带有自增ID的实体
        /// </summary>
        /// <param name="entity">要添加的实体</param>
        /// <returns>添加后的实体（包含自增ID）</returns>
        public async Task<TEntity> AddEntityAsync(TEntity entity)
        {
            // 使用SqlSugar的InsertReturnEntity方法，它会返回插入后的实体（包括自增主键值）
            return await _dbContext.Insertable(entity).ExecuteReturnEntityAsync();
        }

        public async Task<bool> AddRangeAsync(List<TEntity> entities)
        {
            return await _dbContext.Insertable(entities).ExecuteCommandAsync() > 0;
        }

        public async Task<bool> UpdateAsync(TEntity entity)
        {
            return await _dbContext.Updateable(entity).ExecuteCommandAsync() > 0;
        }

        public async Task<bool> UpdateRangeAsync(List<TEntity> entities)
        {
            return await _dbContext.Updateable(entities).ExecuteCommandAsync() > 0;
        }

        public async Task<bool> DeleteAsync(TEntity entity)
        {
            return await _dbContext.Deleteable(entity).ExecuteCommandAsync() > 0;
        }

        public async Task<bool> DeleteByIdAsync(object id)
        {
            return await _dbContext.Deleteable<TEntity>().In(id).ExecuteCommandAsync() > 0;
        }

        public async Task<bool> DeleteRangeAsync(List<TEntity> entities)
        {
            return await _dbContext.Deleteable(entities).ExecuteCommandAsync() > 0;
        }
        #endregion
    }
}